/**
 * 
 */
package nl.boektrust.btsoep.server;

import java.text.DecimalFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;

import org.w3c.dom.Document;
import org.w3c.dom.DocumentFragment;
import org.w3c.dom.Element;

import com.sun.xml.internal.messaging.saaj.packaging.mime.internet.BMMimeMultipart;

import nl.boektrust.btsoep.shared.model.AvailabilityCode;
import nl.boektrust.btsoep.shared.model.BTEntity;
import nl.boektrust.btsoep.shared.model.Book;
import nl.boektrust.btsoep.shared.model.BookManifestation;
import nl.boektrust.btsoep.shared.model.ContentSpecifier;
import nl.boektrust.btsoep.shared.model.ContentSpecifierType;
import nl.boektrust.btsoep.shared.model.Contributor;
import nl.boektrust.btsoep.shared.model.ContributorRoleCode;
import nl.boektrust.btsoep.shared.model.EditionTypeCode;
import nl.boektrust.btsoep.shared.model.ISBN;
import nl.boektrust.btsoep.shared.model.ISBNReference;
import nl.boektrust.btsoep.shared.model.ISBNReferenceType;
import nl.boektrust.btsoep.shared.model.Identifier;
import nl.boektrust.btsoep.shared.model.ImageReference;
import nl.boektrust.btsoep.shared.model.LanguageCode;
import nl.boektrust.btsoep.shared.model.Person;
import nl.boektrust.btsoep.shared.model.PhysicalBookManifestation;
import nl.boektrust.btsoep.shared.model.Price;
import nl.boektrust.btsoep.shared.model.PriceTypeCode;
import nl.boektrust.btsoep.shared.model.ProductFormCode;
import nl.boektrust.btsoep.shared.model.SupplierCode;
import nl.boektrust.btsoep.shared.model.SupplyDetail;
import nl.boektrust.btsoep.shared.model.URLReference;
import nl.boektrust.btsoep.shared.model.URLReferenceType;



/**
 * @author rao3
 *
 */
public class OnixUtility {
	public static String namespaceURI = "http://www.editeur.org/onix/2.1/reference";
	
	public static org.w3c.dom.DocumentFragment getDocumentFragment() {
		DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
		try {
			DocumentBuilder db = factory.newDocumentBuilder();
			org.w3c.dom.Document doc = db.newDocument();
			org.w3c.dom.DocumentFragment documentFragment = doc.createDocumentFragment();
			return documentFragment;

		} catch (Exception e) {
			e.printStackTrace();
		}

		return null;
		
	}

	public static DocumentFragment getLanguageCodeOnix(LanguageCode languageCode) {
		return OnixUtility.getLanguageCodeOnix(languageCode, "01");
	}

	public static DocumentFragment getContributorsOnix(List<Contributor> contributors) {
		if (contributors.size() == 0) return null;
		DocumentFragment documentFragment = OnixUtility.getDocumentFragment();
		Document doc = documentFragment.getOwnerDocument();
	
		int seqno = 0;
		for (Contributor c:contributors) {
			seqno++;
			DocumentFragment f = OnixUtility.encodeToOnix(c, seqno);
			documentFragment.appendChild(doc.importNode(f, true));
		}
		return documentFragment;
	}

	public static DocumentFragment getFirstModificationDateOnix() { 
		return null;
	}

	public static DocumentFragment getLanguageCodeOnix(LanguageCode code, String role) {
		DocumentFragment documentFragment = OnixUtility.getDocumentFragment();
		Document doc = documentFragment.getOwnerDocument();
		if (code == LanguageCode.UNDEFINED) return null;
		if (code == null) {
			System.err.println("Book:getLanguageCodeOnix(): languagecode is null, should have a LanguageCode value");
			return null;
		}
		Element e = documentFragment.getOwnerDocument().createElement("Language");
		try {
			Element e1 = documentFragment.getOwnerDocument().createElement("LanguageRole");
			e1.appendChild(doc.createTextNode(role));
			e.appendChild(e1);
			Element e2 = documentFragment.getOwnerDocument().createElement("LanguageCode");
			e2.appendChild(doc.createTextNode(LanguageCode.stringValueForOnix(code)));
			e.appendChild(e2);
		} catch (Exception ex) {
			System.err.println("Exception thrown in getLanguageCodeOnix");
			ex.printStackTrace();
		};
		documentFragment.appendChild(e);
		return documentFragment;
	}

	public static DocumentFragment getModificationDateOnix(Date modificationDateOnix) { 
		return null;
	}

	public static DocumentFragment getOriginalLanguageCodeOnix(LanguageCode languageCode) {
		return OnixUtility.getLanguageCodeOnix(languageCode, "02");
	}

	/**
	 * @return an ONIX Fragment with both title and subtitle encoded. 
	 * @returns null if title and subtitle are both null or zero length. A documentfragment otherwise. 
	 */
	public static DocumentFragment getOriginalTitleOnix(Book b) {
		DocumentFragment documentFragment = OnixUtility.getDocumentFragment();
		Document doc = documentFragment.getOwnerDocument();
		// do not return a fragment if title and subtitle are both zero-length
		if ((b.getOriginalTitle() == null || b.getOriginalTitle().length() == 0)) {
			return null;
		}
	
		Element e = documentFragment.getOwnerDocument().createElement("Title");
		
		// if originalTitle is not null, add a title node
		if (!(b.getOriginalTitle() == null || b.getOriginalTitle().length() == 0)) {
			try {
				Element e1 = documentFragment.getOwnerDocument().createElement("TitleType");
				e1.appendChild(doc.createTextNode("03"));
				e.appendChild(e1);
				Element e2 = documentFragment.getOwnerDocument().createElement("TitleText");
				e2.appendChild(doc.createTextNode(b.getOriginalTitle()));
				e.appendChild(e2);
			} catch (Exception ex) {};
		}
		documentFragment.appendChild(e);
		return documentFragment;
	}

	/**
	 * @return an ONIX Fragment with both title and subtitle encoded. 
	 * @returns null if title and subtitle are both null or zero length. A documentfragment otherwise. 
	 */
	public static DocumentFragment getTitleOnix(String title, String subtitle) {
		DocumentFragment documentFragment = OnixUtility.getDocumentFragment();
		Document doc = documentFragment.getOwnerDocument();
		// do not return a fragment if title and subtitle are both zero-length
		if ((title == null || title.length() == 0) && (subtitle == null || subtitle.length() == 0)) {
			return null;
		}
	
		Element e = documentFragment.getOwnerDocument().createElement("Title");
		
		// if title is not null, add a title node
		if (!(title == null || title.length() == 0)) {
			try {
				Element e1 = documentFragment.getOwnerDocument().createElement("TitleType");
				e1.appendChild(doc.createTextNode("01"));
				e.appendChild(e1);
				Element e2 = documentFragment.getOwnerDocument().createElement("TitleText");
				e2.appendChild(doc.createTextNode(title));
				e.appendChild(e2);
			} catch (Exception ex) {};
		}
		
		// if substitle is not null, add a subtitle node
		if (!(subtitle == null || subtitle.length() == 0)) { 
			try {
				Element e3 = documentFragment.getOwnerDocument().createElement("Subtitle");
				e3.appendChild(doc.createTextNode(subtitle));
				e.appendChild(e3);
			}  catch (Exception ex) {}
		}
		documentFragment.appendChild(e);
		return documentFragment;
	}

	public static DocumentFragment getEditionOnix(int edition) {
		DocumentFragment documentFragment = OnixUtility.getDocumentFragment();
		Document doc = documentFragment.getOwnerDocument();
		// do not return a fragment if imprint is zero-length
		if ((edition <= 0)) {
			return null;
		}

		Element e = documentFragment.getOwnerDocument().createElement("EditionNumber");
		e.appendChild(doc.createTextNode(new Integer(edition).toString()));
		documentFragment.appendChild(e);
		return documentFragment;	
	}

	public static DocumentFragment getEditionTypeCodeOnix(EditionTypeCode editionTypeCode) {
		DocumentFragment documentFragment = OnixUtility.getDocumentFragment();
		Document doc = documentFragment.getOwnerDocument();
		// do not return a fragment if edition type is undefined
		if (editionTypeCode == EditionTypeCode.UNDEFINED) {
			return null;
		}
	
		Element e = documentFragment.getOwnerDocument().createElement("EditionTypeCode");
		e.appendChild(doc.createTextNode(EditionTypeCode.stringValueForOnix(editionTypeCode)));
		documentFragment.appendChild(e);
		return documentFragment;
	}

	public static DocumentFragment getFirstPublicationDateOnix(Date firstPublicationDate) {
		DocumentFragment documentFragment = OnixUtility.getDocumentFragment();
		Document doc = documentFragment.getOwnerDocument();
		// do not return a fragment if imprint is zero-length
		if ((firstPublicationDate == null)) {
			return null;
		}

		Element e = documentFragment.getOwnerDocument().createElement("YearFirstPublished");
		Calendar c = Calendar.getInstance();
		c.setTime(firstPublicationDate);
		String cstring = new String(""+c.get(Calendar.YEAR));
		e.appendChild(doc.createTextNode(cstring));
		documentFragment.appendChild(e);
		return documentFragment;			
	}

	public static DocumentFragment getImprintOnix(String imprint) {
		DocumentFragment documentFragment = OnixUtility.getDocumentFragment();
		Document doc = documentFragment.getOwnerDocument();
		// do not return a fragment if imprint is zero-length
		if ((imprint == null || imprint.length() == 0)) {
			return null;
		}
	
		Element e = documentFragment.getOwnerDocument().createElement("Imprint");
		Element e1 = documentFragment.getOwnerDocument().createElement("ImprintName");
		e1.appendChild(doc.createTextNode(imprint));
		e.appendChild(e1);
		documentFragment.appendChild(e);
		return documentFragment;
	}

	public static DocumentFragment getNumberOfBWIllustrationsOnix(int numberOfBWIllustrations) {
		DocumentFragment documentFragment = OnixUtility.getDocumentFragment();
		Document doc = documentFragment.getOwnerDocument();
		// do not return a fragment if imprint is zero-length
		if ((numberOfBWIllustrations < 0)) {
			return null;
		}
	
		Element e = documentFragment.getOwnerDocument().createElement("Illustrations");
		Element e1 = documentFragment.getOwnerDocument().createElement("IllustrationType");
		e1.appendChild(doc.createTextNode("01"));
		e.appendChild(e1);
		Element e2 = documentFragment.getOwnerDocument().createElement("Number");
		e2.appendChild(doc.createTextNode(new Integer(numberOfBWIllustrations).toString()));
		e.appendChild(e2);
		documentFragment.appendChild(e);
		return documentFragment;
	}

	public static DocumentFragment getNumberOfColorIllustrationsOnix(int numberOfColorIllustrations) {
		DocumentFragment documentFragment = OnixUtility.getDocumentFragment();
		Document doc = documentFragment.getOwnerDocument();
		// do not return a fragment if imprint is zero-length
		if ((numberOfColorIllustrations < 0)) {
			return null;
		}
	
		Element e = documentFragment.getOwnerDocument().createElement("Illustrations");
		Element e1 = documentFragment.getOwnerDocument().createElement("IllustrationType");
		e1.appendChild(doc.createTextNode("02"));
		e.appendChild(e1);
		Element e2 = documentFragment.getOwnerDocument().createElement("Number");
		e2.appendChild(doc.createTextNode(new Integer(numberOfColorIllustrations).toString()));
		e.appendChild(e2);
		documentFragment.appendChild(e);
		return documentFragment;
	}

	public static DocumentFragment getNumberOfPagesOnix(int numberOfPages) {
		DocumentFragment documentFragment = OnixUtility.getDocumentFragment();
		Document doc = documentFragment.getOwnerDocument();
		// do not return a fragment if imprint is zero-length
		if ((numberOfPages <= 0)) {
			return null;
		}
	
		Element e = documentFragment.getOwnerDocument().createElement("NumberOfPages");
		e.appendChild(doc.createTextNode(new Integer(numberOfPages).toString()));
		documentFragment.appendChild(e);
		return documentFragment;	
	}

	public static DocumentFragment getProductFormCodeOnix(ProductFormCode productFormCode) {
		DocumentFragment documentFragment = OnixUtility.getDocumentFragment();
		Document doc = documentFragment.getOwnerDocument();
		// do not return a fragment if imprint is zero-length
		if (productFormCode == ProductFormCode.UNDEFINED) {
			return null;
		}

		Element e = documentFragment.getOwnerDocument().createElement("ProductForm");
		e.appendChild(doc.createTextNode(ProductFormCode.stringValueForOnix(productFormCode)));
		documentFragment.appendChild(e);
		return documentFragment;	
	}

	public static DocumentFragment getPublicationDateOnix(Date publicationDate) {
		DocumentFragment documentFragment = OnixUtility.getDocumentFragment();
		Document doc = documentFragment.getOwnerDocument();
		// do not return a fragment if imprint is zero-length
		if ((publicationDate == null)) {
			return null;
		}

		Element e = documentFragment.getOwnerDocument().createElement("PublicationDate");
		DecimalFormat twoDigits = new DecimalFormat("00");
		Calendar c = Calendar.getInstance();
		c.setTime(publicationDate);
		String cstring = new String(""+c.get(Calendar.YEAR)+twoDigits.format(c.get(Calendar.MONTH))+twoDigits.format(c.get(Calendar.DAY_OF_MONTH)));
		e.appendChild(doc.createTextNode(cstring));
		documentFragment.appendChild(e);
		return documentFragment;		
	}

	public static DocumentFragment getRecordReferenceOnix(long recordReference) {
		DocumentFragment documentFragment = OnixUtility.getDocumentFragment();
		Document doc = documentFragment.getOwnerDocument();
		// do not return a fragment if imprint is zero-length
		if ((recordReference <= 0)) {
			return null;
		}
	
		Element e = documentFragment.getOwnerDocument().createElement("RecordReference");
		e.appendChild(doc.createTextNode(new Long(recordReference).toString()));
		documentFragment.appendChild(e);
		return documentFragment;
	}

	public static DocumentFragment getSeriesTitleOnix(String seriesTitle) {
		DocumentFragment documentFragment = OnixUtility.getDocumentFragment();
		Document doc = documentFragment.getOwnerDocument();
		// do not return a fragment if series is zero-length
		if ((seriesTitle == null || seriesTitle.length() == 0)) {
			return null;
		}

		Element e = documentFragment.getOwnerDocument().createElement("Series");
		Element e1 = documentFragment.getOwnerDocument().createElement("TitleOfSeries");
		e1.appendChild(doc.createTextNode(seriesTitle));
		e.appendChild(e1);
		documentFragment.appendChild(e);
		return documentFragment;	
	}

	public static DocumentFragment getSetTitleOnix(String setTitle) {
		DocumentFragment documentFragment = OnixUtility.getDocumentFragment();
		Document doc = documentFragment.getOwnerDocument();
		// do not return a fragment if series is zero-length
		if ((setTitle == null || setTitle.length() == 0)) {
			return null;
		}

		Element e = documentFragment.getOwnerDocument().createElement("Set");
		Element e1 = documentFragment.getOwnerDocument().createElement("TitleOfSet");
		e1.appendChild(doc.createTextNode(setTitle));
		e.appendChild(e1);
		documentFragment.appendChild(e);
		return documentFragment;	
	}

	public static DocumentFragment getMeasureOnix(int typecode, int value, String unitcode) {
		DocumentFragment documentFragment = OnixUtility.getDocumentFragment();
		Document doc = documentFragment.getOwnerDocument();
		DecimalFormat twoDigits = new DecimalFormat("00");
		// do not return a fragment if series is zero-length
		if (value == -1 || typecode == -1 || unitcode == null || unitcode.length() == 0) {
			return null;
		}
	
		Element e = documentFragment.getOwnerDocument().createElement("Measure");
		Element e1 = documentFragment.getOwnerDocument().createElement("MeasureTypeCode");
		Element e2 = documentFragment.getOwnerDocument().createElement("Measurement");
		Element e3 = documentFragment.getOwnerDocument().createElement("MeasureUnitCode");
		e1.appendChild(doc.createTextNode(twoDigits.format(typecode)));
		e2.appendChild(doc.createTextNode(new Integer(value).toString()));
		e3.appendChild(doc.createTextNode(unitcode));
		
		e.appendChild(e1);
		e.appendChild(e2);
		e.appendChild(e3);
		documentFragment.appendChild(e);
		return documentFragment;	
	}

	public static DocumentFragment getHeightOnix(int height) {
		return OnixUtility.getMeasureOnix(1, height, "mm");
	}

	public static DocumentFragment getThicknessOnix(int thickness) {
		return OnixUtility.getMeasureOnix(3, thickness, "mm");
	}

	public static DocumentFragment getWeightOnix(int weight) {
		return OnixUtility.getMeasureOnix(8, weight, "gr");
	}

	public static DocumentFragment getWidthOnix(int width) {
		return OnixUtility.getMeasureOnix(2, width, "mm");
	}

	public static DocumentFragment getPriceAmountOnix(int priceAmountInCents) {
		DocumentFragment documentFragment = OnixUtility.getDocumentFragment();
		Document doc = documentFragment.getOwnerDocument();
		// do not return a fragment if edition type is undefined
		if (priceAmountInCents <= 0) {
			return null;
		}
	
		Element e = documentFragment.getOwnerDocument().createElement("PriceAmount");
		//DecimalFormat currency =  (DecimalFormat) DecimalFormat.getCurrencyInstance();// NumberFormat.getCurrencyFormat();
		DecimalFormat currency = new DecimalFormat("###0.00");
		float price = (float)priceAmountInCents / 100;
		e.appendChild(doc.createTextNode(currency.format(price)));
		documentFragment.appendChild(e);
		return documentFragment;	
	}

	public static DocumentFragment getPriceTypeCodeOnix(PriceTypeCode priceTypeCode) {
		DocumentFragment documentFragment = OnixUtility.getDocumentFragment();
		Document doc = documentFragment.getOwnerDocument();
		// do not return a fragment if edition type is undefined
		if (priceTypeCode == PriceTypeCode.UNDEFINED) {
			return null;
		}
	
		Element e = documentFragment.getOwnerDocument().createElement("PriceTypeCode");
		e.appendChild(doc.createTextNode(PriceTypeCode.stringValueForOnix(priceTypeCode)));
		documentFragment.appendChild(e);
		return documentFragment;	
	}

	public static DocumentFragment encodeToOnix(ISBN isbn) {
		// don't encode a URLReference node if the link type is undefined or name is empty
		if (isbn.getIsbn12() == null || isbn.getIsbn12().length() == 0) {
			return null;
		}
		DecimalFormat twoDigits = new DecimalFormat("00");
		
		DocumentFragment documentFragment = OnixUtility.getDocumentFragment();
		Document doc = documentFragment.getOwnerDocument();
		Element e = doc.createElement("ProductIdentifier");
		
		// append the ProductIDType node
		Element e1 = doc.createElement("ProductIDType");
		e1.appendChild(doc.createTextNode(twoDigits.format(03)));
		e.appendChild(e1);
		
		// append the ISBN value node / IDValue
		Element e2 = doc.createElement("IDValue");
		e2.appendChild(doc.createTextNode(isbn.getIsbn13()));
		e.appendChild(e2);
		
		documentFragment.appendChild(e);
		return documentFragment;
	}

	public static DocumentFragment encodeToOnix(ISBNReference isbnReference) {
		ISBNReferenceType isbnReferenceType = isbnReference.getIsbnReferenceType();
		ISBN isbn = isbnReference.getIsbn();
		// don't encode an ISBNReference node if the link type is undefined or isbn is null
		if (isbnReferenceType == ISBNReferenceType.UNDEFINED || isbn == null) {
			return null;
		}
		DecimalFormat twoDigits = new DecimalFormat("00");
		
		DocumentFragment documentFragment = OnixUtility.getDocumentFragment();
		Document doc = documentFragment.getOwnerDocument();
		Element e = doc.createElement("RelatedProduct");
		
		// append the WebsiteRole node
		Element e1 = doc.createElement("RelationCode");
		e1.appendChild(doc.createTextNode(twoDigits.format(ISBNReferenceType.intValueForOnix(isbnReferenceType))));
		e.appendChild(e1);
		
		// append the ISBN encoded node
		e.appendChild(doc.importNode(OnixUtility.encodeToOnix(isbn), true));
	
		documentFragment.appendChild(e);
		return documentFragment;
	}


	public static DocumentFragment getOnixMessage(Date date) {
		DocumentFragment documentFragment = OnixUtility.getDocumentFragment();
		Document doc = documentFragment.getOwnerDocument();
		Element e = doc.createElementNS(OnixUtility.namespaceURI, "ONIXMessage");
		documentFragment.appendChild(e);
		return documentFragment;
	}

	public static DocumentFragment getOnixMessage() {
		return OnixUtility.getOnixMessage(new Date());
	}
	
	
	public static DocumentFragment encodeToOnix(PhysicalBookManifestation pbm) {
		DocumentFragment documentFragment = OnixUtility.getDocumentFragment();
		Document doc = documentFragment.getOwnerDocument();
		if (pbm.getIsbn() == null || pbm.getIsbn().isValidISBN13() == false) return null;
	
		Element e = documentFragment.getOwnerDocument().createElement("Product");
		if (OnixUtility.encodeToOnix(pbm.getIsbn()) != null ) {
			e.appendChild(doc.importNode(OnixUtility.getRecordReferenceOnix(new Long(pbm.getIsbn().getIsbn12()).longValue()), true));
		}
	//	if (OnixUtility.getRecordReferenceOnix(pbm.getRecordReference()) != null ) e.appendChild(doc.importNode(OnixUtility.getRecordReferenceOnix(pbm.getRecordReference()), true));
		Element e1 = doc.createElement("NotificationType");
		e1.appendChild(doc.createTextNode("3"));
		e.appendChild(e1);
		
		// add RecordSourceType node. Always 4. 
		Element e2 = doc.createElement("RecordSourceType");
		e2.appendChild(doc.createTextNode("4"));
		e.appendChild(e2);

		// add RecordSourceName node. Always 'BoekTrust Netherlands bv.'
		Element e3 = doc.createElement("RecordSourceName");
		e3.appendChild(doc.createTextNode("BoekTrust Netherlands bv"));
		e.appendChild(e3);

		if (OnixUtility.encodeToOnix(pbm.getIsbn()) != null ) {
			e.appendChild(doc.importNode(encodeToOnix(pbm.getIsbn()), true));
		}
		if (OnixUtility.getProductFormCodeOnix(pbm.getProductFormCode()) != null ) e.appendChild(doc.importNode(OnixUtility.getProductFormCodeOnix(pbm.getProductFormCode()), true));
		if (OnixUtility.getSetTitleOnix(pbm.getSetTitle()) != null ) e.appendChild(doc.importNode(OnixUtility.getSetTitleOnix(pbm.getSetTitle()), true));
		if (OnixUtility.getTitleOnix(pbm.getTitle(), pbm.getSubtitle()) != null ) e.appendChild(doc.importNode(OnixUtility.getTitleOnix(pbm.getTitle(), pbm.getSubtitle()), true));
		int seqno = 0;
		for (Contributor c : pbm.getContributors()) {
			if (OnixUtility.encodeToOnix(c, seqno) != null) {
				e.appendChild(doc.importNode(OnixUtility.encodeToOnix(c, seqno), true));
				seqno++;
			}
		}
		if (OnixUtility.getEditionTypeCodeOnix(pbm.getEditionTypeCode()) != null ) e.appendChild(doc.importNode(OnixUtility.getEditionTypeCodeOnix(pbm.getEditionTypeCode()), true));
		if (OnixUtility.getEditionOnix(pbm.getEdition()) != null ) e.appendChild(doc.importNode(OnixUtility.getEditionOnix(pbm.getEdition()), true));
		if (OnixUtility.getLanguageCodeOnix(pbm.getLanguageCode()) != null) e.appendChild(doc.importNode(OnixUtility.getLanguageCodeOnix(pbm.getLanguageCode()), true));
		if (OnixUtility.getOriginalLanguageCodeOnix(pbm.getOriginalLanguageCode()) != null) e.appendChild(doc.importNode(OnixUtility.getOriginalLanguageCodeOnix(pbm.getOriginalLanguageCode()), true));
		if (OnixUtility.getNumberOfPagesOnix(pbm.getNumberOfPages()) != null ) e.appendChild(doc.importNode(OnixUtility.getNumberOfPagesOnix(pbm.getNumberOfPages()), true));
		if (OnixUtility.getNumberOfColorIllustrationsOnix(pbm.getNumberOfColorIllustrations()) != null ) e.appendChild(doc.importNode(OnixUtility.getNumberOfColorIllustrationsOnix(pbm.getNumberOfColorIllustrations()), true));
		if (OnixUtility.getNumberOfBWIllustrationsOnix(pbm.getNumberOfBWIllustrations()) != null ) e.appendChild(doc.importNode(OnixUtility.getNumberOfBWIllustrationsOnix(pbm.getNumberOfBWIllustrations()), true));
		for (ContentSpecifier c : pbm.getContentSpecifiers()) {
			e.appendChild(doc.importNode(OnixUtility.encodeToOnix(c), true));
		}
		// add AudienceDescription
		// add AudienceRange
		// add othertexts
		// add mediafiles
		for (ImageReference imageReference : pbm.getImageReferences()) {
			if (OnixUtility.encodeToOnix(imageReference) != null) {
				e.appendChild(doc.importNode(OnixUtility.encodeToOnix(imageReference),true));
			}
		}
		
		if (OnixUtility.getImprintOnix(pbm.getImprint()) != null ) e.appendChild(doc.importNode(OnixUtility.getImprintOnix(pbm.getImprint()), true));
		if (OnixUtility.getPublicationDateOnix(pbm.getPublicationDate()) != null ) e.appendChild(doc.importNode(OnixUtility.getPublicationDateOnix(pbm.getPublicationDate()), true));
		if (OnixUtility.getHeightOnix(pbm.getHeight()) != null ) e.appendChild(doc.importNode(OnixUtility.getHeightOnix(pbm.getHeight()), true));
		if (OnixUtility.getWidthOnix(pbm.getWidth()) != null ) e.appendChild(doc.importNode(OnixUtility.getWidthOnix(pbm.getWidth()), true));
		if (OnixUtility.getThicknessOnix(pbm.getThickness()) != null ) e.appendChild(doc.importNode(OnixUtility.getThicknessOnix(pbm.getThickness()), true));
		if (OnixUtility.getWeightOnix(pbm.getWeight()) != null ) e.appendChild(doc.importNode(OnixUtility.getWeightOnix(pbm.getWeight()), true));
		for (SupplyDetail s : pbm.getSupplyDetails()) {
			if (OnixUtility.encodeToOnix(s) != null) e.appendChild(doc.importNode(OnixUtility.encodeToOnix(s), true));
		}
	
		documentFragment.appendChild(e);
		return documentFragment;
	
		
	}

	public static DocumentFragment encodeToOnix(ImageReference i) {
		DocumentFragment documentFragment = OnixUtility.getDocumentFragment();
		Document doc = documentFragment.getOwnerDocument();
		Element e = doc.createElement("MediaFile");
		Element e1 = doc.createElement("MediaFileTypeCode");
		e1.appendChild(doc.createTextNode(new Integer(i.getImageReferenceTypeCode().toMediaFileLinkTypeCode()).toString()));
		Element e2 = doc.createElement("MediaFileFormatCode");
		e2.appendChild(doc.createTextNode("03"));
		Element e3 = doc.createElement("MediaFileLinkTypeCode");
		e3.appendChild(doc.createTextNode("01"));
		Element e4 = doc.createElement("MediaFileLink");
		e4.appendChild(doc.createTextNode(i.getUrl()));
		e.appendChild(e1);
		e.appendChild(e3);
		e.appendChild(e4);
		documentFragment.appendChild(e);
		return documentFragment;
	}
	
	public static DocumentFragment encodeToOnix(Price p) {
		if (OnixUtility.getPriceAmountOnix(p.getPriceAmountInCents()) == null || OnixUtility.getPriceTypeCodeOnix(p.getPriceTypeCode()) == null) {
			return null;
		}
		DocumentFragment documentFragment = OnixUtility.getDocumentFragment();
		Document doc = documentFragment.getOwnerDocument();
		Element e = documentFragment.getOwnerDocument().createElement("Price");
		Element e1 = documentFragment.getOwnerDocument().createElement("PriceTypeCode");
		e1.appendChild(doc.importNode(OnixUtility.getPriceTypeCodeOnix(p.getPriceTypeCode()), true));
		Element e2 = documentFragment.getOwnerDocument().createElement("PriceAmount");
		e2.appendChild(doc.importNode(OnixUtility.getPriceAmountOnix(p.getPriceAmountInCents()), true));
		e.appendChild(e1);
		e.appendChild(e2);
		documentFragment.appendChild(e);
		return documentFragment;
	}

	public static DocumentFragment getAvailabilityCodeOnix(AvailabilityCode availabilityCode) {
		DocumentFragment documentFragment = OnixUtility.getDocumentFragment();
		Document doc = documentFragment.getOwnerDocument();
		// do not return a fragment if edition type is undefined
		if (availabilityCode == AvailabilityCode.UNDEFINED) {
			return null;
		}
	
		Element e = documentFragment.getOwnerDocument().createElement("AvailabilityCode");
		e.appendChild(doc.createTextNode(AvailabilityCode.stringValueForOnix(availabilityCode)));
		documentFragment.appendChild(e);
		return documentFragment;	
	}

	public static DocumentFragment encodeToOnix(SupplyDetail s) {
		if (OnixUtility.getAvailabilityCodeOnix(s.getAvailabilityCode()) == null || s.getPriceArray().size() <= 0) {
			return null;
		}
		DocumentFragment documentFragment = OnixUtility.getDocumentFragment();
		Document doc = documentFragment.getOwnerDocument();
		Element e = documentFragment.getOwnerDocument().createElement("SupplyDetail");
		Element e1 = documentFragment.getOwnerDocument().createElement("SupplierName");
		String supplierName = "Onbekend";
		/*
		 * use suppliercode if available; otherwise name if available; otherwise "Onbekend"
		 */
		if (s.getSupplier().getSupplierCode() != null && s.getSupplier().getSupplierCode() != SupplierCode.UNDEFINED) {
			supplierName = SupplierCode.stringValue(s.getSupplier().getSupplierCode());
		} else if (s.getSupplier().getName() != null) {
			supplierName = s.getSupplier().getName();	
		} 
		e1.appendChild(doc.importNode(OnixUtility.getNameOnix(supplierName), true));
		e.appendChild(e1);
		Element e2 = documentFragment.getOwnerDocument().createElement("SupplierRole");
		Element e3 = documentFragment.getOwnerDocument().createElement("AvailabilityCode");
		
		e2.appendChild(doc.createTextNode("0"));
		e.appendChild(e2);
		e3.appendChild(doc.importNode(OnixUtility.getAvailabilityCodeOnix(s.getAvailabilityCode()), true));
		e.appendChild(e3);
		for (Price p : s.getPriceArray()) {
			if (OnixUtility.encodeToOnix(p) != null) e.appendChild(doc.importNode(OnixUtility.encodeToOnix(p), true));
		}
		documentFragment.appendChild(e);
		return documentFragment;	
	}

	public static DocumentFragment encodeToOnix(URLReference u) {
		// don't encode a URLReference node if the link type is undefined or name is empty
		if (u.getUrlReferenceType() == URLReferenceType.UNDEFINED || u.getUrl() == null || u.getUrl().length() == 0) {
			return null;
		}
		
		DocumentFragment documentFragment = OnixUtility.getDocumentFragment();
		Document doc = documentFragment.getOwnerDocument();
		Element e = doc.createElement("ProductWebsite");
		DecimalFormat twoDigits = new DecimalFormat("00");
		
		// append the WebsiteRole node
		Element e1 = doc.createElement("WebsiteRole");
		e1.appendChild(doc.createTextNode(twoDigits.format(URLReferenceType.intValueForOnix(u.getUrlReferenceType()))));
		e.appendChild(e1);
		
		// append the ProductWebsiteDescription node
		Element e2 = doc.createElement("ProductWebsiteDescription");
		e2.appendChild(doc.createTextNode(URLReferenceType.stringValue(u.getUrlReferenceType())));
		e.appendChild(e2);
		
		Element e3 = doc.createElement("ProductWebsiteLink");
		e3.appendChild(doc.createTextNode(u.getUrl()));
		e.appendChild(e3);
		documentFragment.appendChild(e);
		return documentFragment;
	}

	public static DocumentFragment getNameOnix(String name) {
		if (name == null || name.length() == 0) return null;
		DocumentFragment documentFragment = OnixUtility.getDocumentFragment();
		Document doc = documentFragment.getOwnerDocument();
		Element e = doc.createElement("PersonName");
		e.appendChild(doc.createTextNode(name));
		documentFragment.appendChild(e);		
		return documentFragment;
	}

	public static DocumentFragment encodeToOnix(ContentSpecifier c) {
		// don't encode a URLReference node if the link type is undefined or name is empty
		if (c.getContentSpecifierType() == ContentSpecifierType.UNDEFINED) {
			return null;
		}
		DecimalFormat twoDigits = new DecimalFormat("00");
		DecimalFormat threeDigits = new DecimalFormat("000");
		
		DocumentFragment documentFragment = OnixUtility.getDocumentFragment();
		Document doc = documentFragment.getOwnerDocument();
		Element e = doc.createElement("Subject");
		
		// if this is a NUR code, encode as mainSubject 32
		if (c.getContentSpecifierType() == ContentSpecifierType.NURCODE) {
		// append the MainSubjectScheme node
			Element e1 = doc.createElement("SubjectSchemeIdentifier");
			e1.appendChild(doc.createTextNode(twoDigits.format(32)));
			e.appendChild(e1);
			Element e2 = doc.createElement("SubjectCode");
			e2.appendChild(doc.createTextNode(threeDigits.format(c.getCode())));
			e.appendChild(e2);
		} else 	if (c.getContentSpecifierType() == ContentSpecifierType.GEOCODE) {
		// append the MainSubjectScheme node
			Element e1 = doc.createElement("SubjectSchemeIdentifier");
			e1.appendChild(doc.createTextNode(twoDigits.format(23)));
			e.appendChild(e1);
			Element e2 = doc.createElement("SubjectSchemeName");
			e2.appendChild(doc.createTextNode("BoekTrust geocode"));
			e.appendChild(e2);
			Element e3 = doc.createElement("SubjectCode");
			e3.appendChild(doc.createTextNode(c.getDescription()));
			e.appendChild(e3);
		}
	
		
		
		documentFragment.appendChild(e);
		return documentFragment;
	}

	public static DocumentFragment encodeToOnix(Contributor c, int sequenceNumber) {
		// don't encode a contributor node if the role is undefined or name is empty
		if (c.getRoleCode() == ContributorRoleCode.UNDEFINED || c.getNameOnBook() == null || c.getNameOnBook().length() == 0) {
			return null;
		}
		
		DocumentFragment documentFragment = OnixUtility.getDocumentFragment();
		Document doc = documentFragment.getOwnerDocument();
		Element e = doc.createElement("Contributor");
		
		// append the sequneceNumber node
		Element e1 = doc.createElement("SequenceNumber");
		e1.appendChild(doc.createTextNode(new Integer(sequenceNumber).toString()));
		e.appendChild(e1);
		
		// append the ContributorRole node
		e.appendChild(doc.importNode(OnixUtility.getRoleCodeOnix(c.getRoleCode()), true));
	
		// append the PersonName node
		e.appendChild(doc.importNode(OnixUtility.getNameOnBookOnix(c.getNameOnBook()), true));
		
		if (c.getPerson() != null) {
			// append the PersonNameIdentifier if found 
			for (Identifier id : c.getPerson().getIdentifiers()) {
				if (id.getType() == 1) {
					e.appendChild(doc.importNode(encodeToOnix(id), true));
				}
			}
			// append the Name node
			e.appendChild(doc.importNode(OnixUtility.getPersonOnix(c.getPerson()), true));
		}
		// return the documentfragment
		documentFragment.appendChild(e);
		return documentFragment;
	}

	public static DocumentFragment getNameOnBookOnix(String nameOnBook) {
		if (nameOnBook != null && nameOnBook.length() > 0) {
			DocumentFragment documentFragment = OnixUtility.getDocumentFragment();
			Document doc = documentFragment.getOwnerDocument();	
			Element e = doc.createElement("PersonName");
			e.appendChild(doc.createTextNode(nameOnBook));
			documentFragment.appendChild(e);
			return documentFragment;
		}
		return null;
	}

	public static DocumentFragment getPersonOnix(Person person) {
		if (person != null) {
			DocumentFragment documentFragment = OnixUtility.getDocumentFragment();
			Document doc = documentFragment.getOwnerDocument();
			Element e = doc.createElement("Name");
			Element e1 = doc.createElement("PersonNameType");
			e1.appendChild(doc.createTextNode("04"));
			e.appendChild(e1);
			DocumentFragment e2 = OnixUtility.getNameOnix(person.getName());
			doc.importNode(e2, true);
			e.appendChild(doc.importNode(e2, true));
			documentFragment.appendChild(e);
			return documentFragment;
		}
		
		return null;
	}

	public static DocumentFragment getRoleCodeOnix(ContributorRoleCode contributorRoleCode) {
		if (contributorRoleCode == ContributorRoleCode.UNDEFINED) return null;
		DocumentFragment documentFragment = OnixUtility.getDocumentFragment();
		Document doc = documentFragment.getOwnerDocument();
		Element e = doc.createElement("ContributorRole");
		e.appendChild(doc.createTextNode(ContributorRoleCode.stringValueForOnix(contributorRoleCode)));
		documentFragment.appendChild(e);		
		return documentFragment;
	}

	public static DocumentFragment encodeToOnix(Identifier i) {
		// if type is -1 or value is "" or null, don't encode anything
		if (i.getType() == -1 || i.getValue() == null || i.getValue().length() == 0) return null;
		DocumentFragment documentFragment = OnixUtility.getDocumentFragment();
		Document doc = documentFragment.getOwnerDocument();
	
		Element e = documentFragment.getOwnerDocument().createElement("PersonNameIdentifier");
	
		// if type == 1, encode as viaf
		if (i.getType() == 1) {
			Element e1 = documentFragment.getOwnerDocument().createElement("PersonNameIDType");
			
			e1.appendChild(doc.createTextNode("01"));
			e.appendChild(e1);
	
			Element e2 = documentFragment.getOwnerDocument().createElement("IDTypeName");
			e2.appendChild(doc.createTextNode("VIAF"));
			e.appendChild(e2);
		}
		
		Element e3 = documentFragment.getOwnerDocument().createElement("IDValue");
		e3.appendChild(doc.createTextNode(i.getValue()));
		e.appendChild(e3);
		
		documentFragment.appendChild(e);
		return documentFragment;
	}
	
	public static DocumentFragment getOnixMessageHeader() {
		DocumentFragment documentFragment = OnixUtility.getDocumentFragment();
		Document doc = documentFragment.getOwnerDocument();
		Element e = doc.createElement("Header");
		Element e1 = doc.createElement("SenderIdentifier");
		e.appendChild(e1);
		
		Element e1a = doc.createElement("SenderIDType");
		e1a.appendChild(doc.createTextNode("10"));
		e1.appendChild(e1a);

		Element e1b = doc.createElement("IDValue");
		e1b.appendChild(doc.createTextNode("9066342"));
		e1.appendChild(e1b);

		Element e2 = doc.createElement("FromCompany");
		e2.appendChild(doc.createTextNode("BoekTrust bv"));
		e.appendChild(e2);

		Element e3 = doc.createElement("FromEmail");
		e3.appendChild(doc.createTextNode("info@boektrust.nl"));
		e.appendChild(e3);

		Element e4 = doc.createElement("SentDate");
		Calendar c = Calendar.getInstance();
		DecimalFormat twoDigits = new DecimalFormat("00");
		c.setTime(new Date());
		String cstring = new String(""+
				c.get(Calendar.YEAR)+
				twoDigits.format(c.get(Calendar.MONTH)+1)+
				twoDigits.format(c.get(Calendar.DAY_OF_MONTH)) +
				twoDigits.format(c.get(Calendar.HOUR_OF_DAY))+
				twoDigits.format(c.get(Calendar.MINUTE))
				);

		e4.appendChild(doc.createTextNode(cstring));
		e.appendChild(e4);

		Element e5 = doc.createElement("DefaultLanguageOfText");
		e5.appendChild(doc.createTextNode("dut"));
		e.appendChild(e5);

		Element e6 = doc.createElement("DefaultCurrencyCode");
		e6.appendChild(doc.createTextNode("EUR"));
		e.appendChild(e6);

		documentFragment.appendChild(e);
		return documentFragment;		
	}

}
